import os
import threading
import time
from datetime import datetime
from PyQt5.QtWidgets import QApplication, QWidget, QButtonGroup, QMessageBox, QPlainTextEdit
from PyQt5.QtCore import *
from PyQt5.QtGui import QIcon, QRegExpValidator
from PyQt5 import uic
import sys
import re
from PyQt5.QtCore import QTimer
from S_AES import *
'''
提供十六位的明密文、keys
对于二进制：四个十六进制->二进制->hex
ASCII：16个ASCII
'''
from collections import defaultdict
class WorkerSignals(QObject):
    # progress: (worker_id:int, percent:int)
    progress = pyqtSignal(int, int)
    # found: (worker_id:int, key_str:str)
    found = pyqtSignal(int, str)
    finished = pyqtSignal(int)
    log = pyqtSignal(str)

# ---------- 子 Worker：构建 k1 部分表（本地表合并 + 用整数键） ----------
class S_AES_BuildWorker(QObject):
    def __init__(self, worker_id, start, end, pairs, table, table_lock, stop_event):
        super().__init__()
        self.worker_id = worker_id
        self.start = start
        self.end = end
        self.pairs = pairs
        self.table = table
        self.table_lock = table_lock
        self.stop_event = stop_event
        self.signals = WorkerSignals()

    @pyqtSlot()
    def run(self):
        total = max(1, self.end - self.start)
        # 每 worker 汇报 ~100 次
        report_interval = max(1, total // 100)
        local = {}  # 局部表： key(tuple of ints) -> [k_hex,...]
        try:
            sa = S_AES("0000")  # 复用实例，避免频繁构造
            for idx, k in enumerate(range(self.start, self.end), start=1):
                if self.stop_event.is_set():
                    if idx % report_interval == 0 or idx == total:
                        self.signals.log.emit(f"BuildWorker {self.worker_id}: 收到取消，已处理 {idx}/{total}")
                    break

                k_hex = "{:04X}".format(k)
                # 先生成 round keys（Generate_Round_Keys 可被重复调用）
                sa.Generate_Round_Keys(k_hex)
                mid_vals = []
                for p_hex, _ in self.pairs:
                    sa.changePlainText(p_hex.upper())
                    sa.Encryption()
                    # 以 int 存储
                    mid_vals.append(int(sa.cipherText, 16))
                key = tuple(mid_vals)
                # 写到局部表（避免频繁锁）
                lst = local.get(key)
                if lst is None:
                    local[key] = [k_hex]
                else:
                    lst.append(k_hex)

                # 只在 interval 时报告进度与日志
                if idx % report_interval == 0 or idx == total:
                    percent = int((idx / total) * 50)  # 阶段1 占 0..50%
                    self.signals.progress.emit(self.worker_id, percent)
                    self.signals.log.emit(f"BuildWorker {self.worker_id}: 进度 {idx}/{total} ({percent}%)")

            # 循环结束后一次性合并局部表到共享表（加锁短时合并）
            if local:
                with self.table_lock:
                    for k_tuple, klist in local.items():
                        if k_tuple in self.table:
                            self.table[k_tuple].extend(klist)
                        else:
                            # 直接指向同一个 list（不复制）
                            self.table[k_tuple] = list(klist)

            self.signals.log.emit(f"BuildWorker {self.worker_id}: 阶段1 区间 {self.start}-{self.end} 完成，表项合并完成。")
        except Exception as e:
            self.signals.log.emit(f"BuildWorker {self.worker_id} 异常: {e}")
        finally:
            # 发出 finished（由 controller 在主线程统计）
            self.signals.finished.emit(self.worker_id)


# ---------- 子 Worker：枚举 k2 并查表（用 int 键查找） ----------
class S_AES_SearchWorker(QObject):
    def __init__(self, worker_id, start, end, pairs, table, table_lock, stop_event):
        super().__init__()
        self.worker_id = worker_id
        self.start = start
        self.end = end
        self.pairs = pairs
        self.table = table
        self.table_lock = table_lock
        self.stop_event = stop_event
        self.signals = WorkerSignals()

    @pyqtSlot()
    def run(self):
        total = max(1, self.end - self.start)
        report_interval = max(1, total // 100)
        found_local = 0
        try:
            sa = S_AES("0000")
            for idx, k in enumerate(range(self.start, self.end), start=1):
                if self.stop_event.is_set():
                    if idx % report_interval == 0 or idx == total:
                        self.signals.log.emit(f"SearchWorker {self.worker_id}: 收到取消，已处理 {idx}/{total}")
                    break

                k_hex = "{:04X}".format(k)
                sa.Generate_Round_Keys(k_hex)
                mid_vals = []
                for _, c_hex in self.pairs:
                    sa.changeCipherText(c_hex.upper())
                    sa.Decryption()
                    # Decryption 得到的中间明文用 int
                    mid_vals.append(int(sa.plainText, 16))
                key = tuple(mid_vals)

                # 读表（短时加锁以确保内存一致性，但通常为只读）
                with self.table_lock:
                    hits = self.table.get(key)
                if hits:
                    for k1_hex in hits:
                        found_local += 1
                        self.signals.found.emit(self.worker_id, f"{k1_hex},{k_hex}")
                        # 少量日志即可
                        if found_local <= 5 or found_local % 100 == 0:
                            self.signals.log.emit(f"SearchWorker {self.worker_id}: 发现候选 (k1={k1_hex}, k2={k_hex})")

                # 进度报告
                if idx % report_interval == 0 or idx == total:
                    percent = 50 + int((idx / total) * 50)
                    self.signals.progress.emit(self.worker_id, percent)
                    self.signals.log.emit(f"SearchWorker {self.worker_id}: 进度 {idx}/{total} ({percent}%)")

            self.signals.log.emit(f"SearchWorker {self.worker_id}: 区间 {self.start}-{self.end} 完成，局部发现 {found_local} 个候选。")
        except Exception as e:
            self.signals.log.emit(f"SearchWorker {self.worker_id} 异常: {e}")
        finally:
            self.signals.finished.emit(self.worker_id)


# ---------- 控制器：用“计数 finished 回调”替代轮询监测，启动阶段2 更稳健 ----------
class S_AES_MITMController(QObject):
    def __init__(self, pairs, num_threads=4, stop_event=None):
        super().__init__()
        self.pairs = pairs
        self.num_threads = max(1, num_threads)
        self.stop_event = stop_event or threading.Event()
        self.table = dict()      # 共享中间表（键为 tuple(int,...), 值为 [k1_hex,...]）
        self.table_lock = threading.Lock()

        # 状态跟踪
        self.build_threads = []   # QThread 列表（阶段1）
        self.search_threads = []  # QThread 列表（阶段2）
        self._build_total = 0
        self._build_finished = 0
        self._search_total = 0
        self._search_finished = 0

        self._emit_log = lambda text: print("[MITM LOG]", text)
        self._emit_progress = lambda wid, pct: print(f"[MITM PROG] worker={wid} percent={pct}%")
        self._emit_found = lambda wid, keystr: print(f"[MITM FOUND] worker={wid} -> {keystr}")

    def start(self):
        # 阶段1：构建 build workers
        key_space = 1 << 16
        slice_size = (key_space + self.num_threads - 1) // self.num_threads
        self.build_threads = []
        self._build_total = 0
        self._build_finished = 0

        for i in range(self.num_threads):
            s = i * slice_size
            e = min(s + slice_size, key_space)
            if s >= e: continue
            worker = S_AES_BuildWorker(i, s, e, self.pairs, self.table, self.table_lock, self.stop_event)
            thread = QThread()
            worker.moveToThread(thread)
            # 连接：worker -> controller 的桥接（controller 再转发到 UI）
            worker.signals.log.connect(self._emit_log)
            worker.signals.progress.connect(self._emit_progress)
            # 每个 worker 发 finished 都走到 _on_build_finished（在主线程执行）
            worker.signals.finished.connect(self._on_build_finished)
            # 也确保线程退出
            worker.signals.finished.connect(thread.quit)
            # thread 生命周期管理
            thread.started.connect(worker.run)
            thread.finished.connect(thread.deleteLater)

            self.build_threads.append((thread, worker))
            self._build_total += 1

        # 启动所有 build 线程
        for th, _ in self.build_threads:
            th.start()

        self._emit_log(f"MITMController: 已启动 {self._build_total} 个 BuildWorker，开始构建中间表...")

    @pyqtSlot(int)
    def _on_build_finished(self, worker_id):
        # 在主线程被调用（pyqt 的信号槽保证）
        self._build_finished += 1
        self._emit_log(f"MITMController: BuildWorker {worker_id} finished ({self._build_finished}/{self._build_total})")
        # 若全部完成则在主线程马上启动阶段2（使用 singleShot 确保事件循环安全）
        if self._build_finished >= self._build_total:
            # 将 table 冻结（可选做深拷贝以防未来误改）
            self._emit_log(f"MITMController: 阶段1 全部完成，表项数 = {len(self.table)}。准备启动阶段2...")
            QTimer.singleShot(0, self._start_phase2)

    def _start_phase2(self):
        # 若在等待期间主程序请求取消，则不启动
        if self.stop_event.is_set():
            self._emit_log("MITMController: 收到取消标志，放弃启动阶段2。")
            return

        # 启动 SearchWorker
        key_space = 1 << 16
        slice_size = (key_space + self.num_threads - 1) // self.num_threads
        self.search_threads = []
        self._search_total = 0
        self._search_finished = 0

        for i in range(self.num_threads):
            s = i * slice_size
            e = min(s + slice_size, key_space)
            if s >= e: continue
            worker = S_AES_SearchWorker(i, s, e, self.pairs, self.table, self.table_lock, self.stop_event)
            thread = QThread()
            worker.moveToThread(thread)
            worker.signals.log.connect(self._emit_log)
            worker.signals.progress.connect(self._emit_progress)
            worker.signals.found.connect(self._emit_found)
            worker.signals.finished.connect(self._on_search_finished)
            worker.signals.finished.connect(thread.quit)
            thread.started.connect(worker.run)
            thread.finished.connect(thread.deleteLater)

            self.search_threads.append((thread, worker))
            self._search_total += 1

        for th, _ in self.search_threads:
            th.start()

        self._emit_log(f"MITMController: 阶段2 启动，{self._search_total} 个 SearchWorker 开始查表。")

    @pyqtSlot(int)
    def _on_search_finished(self, worker_id):
        self._search_finished += 1
        self._emit_log(f"MITMController: SearchWorker {worker_id} finished ({self._search_finished}/{self._search_total})")
        if self._search_finished >= self._search_total:
            self._emit_log("MITMController: 阶段2 全部完成。")


class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.init_ui()
        self.tabWidget.setCurrentIndex(0)
        self.stop_event = threading.Event()
    def init_ui(self):
        self.setWindowIcon(QIcon('./ui/keys.png'))
        self.ui = uic.loadUi('./ui/mainWindow.ui', self)
        self.setWindowTitle("S-AES演示")
        # 按钮绑定
        #第一页：加解密
        self.Hex = self.ui.radioButton
        self.Ascii = self.ui.radioButton_2
        self.Encryption = self.ui.radioButton_3
        self.Decryption = self.ui.radioButton_4
        self.input_group = QButtonGroup(self)
        self.input_group.addButton(self.Hex)
        self.input_group.addButton(self.Ascii)
        self.Hex.setChecked(True)
        self.mode_group = QButtonGroup(self)
        self.mode_group.addButton(self.Encryption)
        self.mode_group.addButton(self.Decryption)
        self.Encryption.setChecked(True)
        self.text = self.ui.lineEdit
        self.key = self.ui.lineEdit_2
        self.result = self.ui.textBrowser
        self.start = self.ui.pushButton
        #第二页：多重加解密
        self.cryptionGroup = QButtonGroup(self)
        self.double = self.ui.radioButton_6
        self.tripple = self.ui.radioButton_5
        self.cryptionEn = self.ui.radioButton_7
        self.cryptionDe = self.ui.radioButton_8
        self.cryptionGroup.addButton(self.double)
        self.cryptionGroup.addButton(self.tripple)
        self.mode_group_new = QButtonGroup(self)
        self.mode_group_new.addButton(self.cryptionEn)
        self.mode_group_new.addButton(self.cryptionDe)
        self.startCryption = self.ui.pushButton_4
        self.text_new = self.ui.lineEdit_3
        self.key_new = self.ui.lineEdit_4
        self.result_new = self.ui.textBrowser_4
        #第三页：二重加密的中间相遇攻击
        self.plainText_power = self.ui.plainTextEdit
        self.cipherText_power = self.ui.plainTextEdit_2
        self.attach_plaintext_limiter(self.plainText_power)
        self.attach_plaintext_limiter(self.cipherText_power)
        self.result_key = self.ui.textBrowser_3
        self.btnPower = self.ui.pushButton_2
        self.progressBar = self.ui.progressBar

        #第四页：CBC模式
        self.text_CBC = self.ui.plainTextEdit_3
        self.group_CBC = QButtonGroup(self)
        self.key_CBC = self.ui.lineEdit_5
        self.initial_vector = self.ui.lineEdit_6
        self.CBC_Encryption = self.ui.radioButton_10
        self.CBC_Decryption = self.ui.radioButton_9
        self.group_CBC.addButton(self.CBC_Decryption)
        self.group_CBC.addButton(self.CBC_Encryption)
        self.result_CBC = self.ui.textBrowser_2
        self.btnStartCBC = self.ui.pushButton_3
        # 事件绑定
        self.start.clicked.connect(self.startSAES)  # 开始
        self.Ascii.toggled.connect(self.switch_input_mode)  # 切换模式
        self.Hex.toggled.connect(self.switch_input_mode)  # 切换模式
        self.startCryption.clicked.connect(self.startNew)   #开始多重加密
        self.btnPower.clicked.connect(self.start_SAES_MITM)  # 开始暴力破解
        self.btnStartCBC.clicked.connect(self.start_CBC) #开始CBC
        # 补充：key的正则检验
        key_hex_validator = QRegExpValidator(QRegExp("^[0-9A-Fa-f]{4}$"))  # 0-f,最多四位
        self.key.clear()
        self.key.setValidator(key_hex_validator)
        self.text_new.setValidator(key_hex_validator)
        self.key_new.setValidator(QRegExpValidator(QRegExp("^[0-9A-Fa-f]{8}$"))) #0-f,最多八位
        self.key_CBC.setValidator(key_hex_validator)
        self.attach_plaintext_limiter(self.text_CBC,max_len=1024,max_lines=1024)
        self.initial_vector.setValidator(key_hex_validator)
    def startSAES(self):
        self.result.clear()
        text_CP = self.text.text()
        key = self.key.text()
        result = ""
        if len(key) != 4:
            QMessageBox.information(self, "提示", "秘钥需4位,请重新输入", QMessageBox.Ok)
            return
        if self.Hex.isChecked():
            if len(text_CP) != 4:
                QMessageBox.information(self, "提示", "明文/密文需4位,请重新输入", QMessageBox.Ok)
                return
            AES = S_AES(key)
            if self.Encryption.isChecked():
                AES.changePlainText(text_CP)
                AES.Encryption()
                result = AES.cipherText
            elif self.Decryption.isChecked():
                AES.changeCipherText(text_CP)
                AES.Decryption()
                result = AES.plainText
        elif self.Ascii.isChecked():
            AES = S_AES(key)
            if self.Encryption.isChecked():
                result = repr(AES.AsciiEncryption(text_CP))
                result = result + "\n加密结果(包括不可见字符):\n" + AES.cipherText
            elif self.Decryption.isChecked():
                result = repr(AES.AsciiDecryption(text_CP))
                result = result + "\n解密结果(包括不可见字符):\n" + AES.plainText
        self.showResult(text_CP, result,self.result)
    def switch_input_mode(self):
        # 设置验证器
        ascii_validator = None
        hex_validator = QRegExpValidator(QRegExp("^[0-9A-Fa-f]{4}$"))  # 0-f,最多四位
        if self.Ascii.isChecked():
            self.text.clear()
            self.text.setValidator(ascii_validator)
        elif self.Hex.isChecked():
            self.text.clear()
            self.text.setValidator(hex_validator)
        self.result.clear()
    def showResult(self,text,result,resultWindow,mode=False,iv=""):
        resultWindow.clear()
        ans = ""
        if self.Decryption.isChecked() or self.cryptionDe.isChecked():
            ans = text + "的解密结果是:\n"+result
        elif self.Encryption.isChecked() or self.cryptionEn.isChecked():
            ans = text + "的加密结果是:\n" + result
        if mode:
            ans += "\n初始向量为：\n" + iv
        resultWindow.setText(ans)

    """
    双重加密与三重加密
    给定十六位二进制（4hex）明密文
    给定32位二进制（8hex）key
    """
    def startNew(self):
        self.result_new.clear()
        text_CP = self.text_new.text()
        key = self.key_new.text()
        result = ""
        if len(key) != 8:
            QMessageBox.information(self, "提示", "秘钥需8位,请重新输入", QMessageBox.Ok)
            return
        if len(text_CP) != 4:
            QMessageBox.information(self, "提示", "明文/密文需4位,请重新输入", QMessageBox.Ok)
            return
        AES = S_AES("1234")
        if self.double.isChecked():
            if self.cryptionEn.isChecked():
                AES.changePlainText(text_CP)
                AES.DoubleEncryption(key)
                result = AES.cipherText
            elif self.cryptionDe.isChecked():
                AES.changeCipherText(text_CP)
                AES.DoubleDecryption(key)
                result = AES.plainText
        elif self.tripple.isChecked():
            if self.cryptionEn.isChecked():
                AES.changePlainText(text_CP)
                AES.TrippleEncryption(key)
                result = AES.cipherText
            elif self.cryptionDe.isChecked():
                AES.changeCipherText(text_CP)
                AES.TrippleDecryption(key)
                result = AES.plainText
        self.showResult(text_CP, result,self.result_new)

    def start_SAES_MITM(self):
        # 从两个 QTextEdit 里读取明文与密文（每行一个 4-hex）
        plain_input = self.plainText_power.toPlainText().strip()
        cipher_input = self.cipherText_power.toPlainText().strip()

        # 复用你的 parse_pairs（但需要求 4 hex 长度）：
        try:
            pairs = self.parse_pairs_hex4(plain_input, cipher_input)
        except ValueError as e:
            QMessageBox.information(self, "输入错误", str(e), QMessageBox.Ok)
            return

        # 如果已有运行中的 MITM，可先 request cancel
        if hasattr(self, 'mitm_controller') and self.mitm_controller and any(
                th.isRunning() for th in getattr(self.mitm_controller, 'threads', [])):
            self.stop_event.set()
            self.result_key.append("[INFO] 已请求取消上一 MITM 任务")
            return

        # 清理状态
        self.stop_event.clear()
        self.result_key.clear()
        self.progressBar.setValue(0)

        # 创建并启动 controller
        self.mitm_controller = S_AES_MITMController(pairs, num_threads=4, stop_event=self.stop_event)

        # 让 controller 的 emit 方法转到你的 UI handler：
        # 替换控制器的桥接函数为你的 UI 槽
        self.mitm_controller._emit_log = lambda text: self.handle_worker_log(text)
        self.mitm_controller._emit_progress = lambda wid, pct: self.handle_worker_progress(wid, pct)
        self.mitm_controller._emit_found = lambda wid, keystr: self.handle_worker_found(wid, keystr)

        self.mitm_controller.start()
        self.result_key.append("[INFO] 已启动 S_AES MITM（双重加密）任务。")

    def parse_pairs_hex4(self, plain_str, cipher_str):
        def clean(s: str) -> str:
            if s is None: return ""
            s = s.replace('\ufeff', '').replace('\u200b', '').strip()
            return s

        plain_lines = [ln.strip() for ln in clean(plain_str).splitlines() if ln.strip()]
        cipher_lines = [ln.strip() for ln in clean(cipher_str).splitlines() if ln.strip()]
        if not plain_lines or not cipher_lines:
            raise ValueError("明文或密文为空，请至少输入一行 4-hex 字串。")
        if len(plain_lines) != len(cipher_lines):
            raise ValueError("明文与密文行数不一致。")
        pairs = []
        import re
        for i, (p, c) in enumerate(zip(plain_lines, cipher_lines), start=1):
            if not re.fullmatch(r'[0-9A-Fa-f]{4}', p):
                raise ValueError(f"第{i}行明文格式错误（应为4 hex）：{p}")
            if not re.fullmatch(r'[0-9A-Fa-f]{4}', c):
                raise ValueError(f"第{i}行密文格式错误（应为4 hex）：{c}")
            pairs.append((p.upper(), c.upper()))
        return pairs

    def handle_worker_found(self, worker_id, key_str):
        k1_hex, k2_hex = key_str.split(',')
        # 可选：做最终验证（逐对检查 E_k2(E_k1(P)) == C）
        ok = self.verify_candidate_pair(self.mitm_controller.pairs, k1_hex, k2_hex)
        now = datetime.now().strftime('%H:%M:%S.%f')[:-3]
        if ok:
            self.result_key.append(f"[{now}] 找到可信候选: k1={k1_hex}, k2={k2_hex}")
        else:
            self.result_key.append(f"[{now}] 伪候选（未通过验证）: k1={k1_hex}, k2={k2_hex}")

    def verify_candidate_pair(self, pairs, k1_hex, k2_hex):
        for p_hex, c_hex in pairs:
            sa1 = S_AES(k1_hex)
            sa1.changePlainText(p_hex)
            sa1.Encryption()
            mid = sa1.cipherText.upper()
            sa2 = S_AES(k2_hex)
            sa2.changePlainText(mid)
            sa2.Encryption()
            if sa2.cipherText.upper() != c_hex:
                return False
        return True

    def attach_plaintext_limiter(self,widget: QPlainTextEdit, max_lines=1024, max_len=4):
        """
        限制 QPlainTextEdit 输入：
          - 只允许 十六进制
          - 每行最多 max_len 个字符
          - 最多 max_lines 行
          - 可正常回车换行
        """
        def on_text_changed():
            cursor = widget.textCursor()
            text = widget.toPlainText()

            # 拆分行
            lines = text.splitlines()
            modified = False

            # 限制行数
            if len(lines) > max_lines:
                lines = lines[:max_lines]
                modified = True

            new_lines = []
            for line in lines:
                filtered = re.sub(r'[^0-9a-fA-F]', '', line)
                if len(filtered) > max_len:
                    filtered = filtered[:max_len]
                if filtered != line:
                    modified = True
                new_lines.append(filtered)

            if modified:
                block = cursor.blockNumber()
                col = cursor.positionInBlock()

                widget.blockSignals(True)
                widget.setPlainText("\n".join(new_lines))
                widget.blockSignals(False)

                # 恢复光标位置
                doc = widget.document()
                blocks = min(block, len(new_lines) - 1)
                new_block = doc.findBlockByNumber(blocks)
                new_cursor = widget.textCursor()
                new_cursor.setPosition(new_block.position() + min(col, len(new_lines[blocks])))
                widget.setTextCursor(new_cursor)

        widget.textChanged.connect(on_text_changed)

    # 添加到 MainWindow 类中
    def handle_worker_log(self, text):
        """把 worker 的日志显示到 result_key（textBrowser）"""
        now = datetime.now().strftime('%H:%M:%S.%f')[:-3]
        # 确保 result_key 存在并是 QTextBrowser
        try:
            self.result_key.append(f"[{now}] {text}")
        except Exception:
            print("日志显示失败：", text)

    def handle_worker_progress(self, worker_id, percent):
        """
        使用简单的平均法更新 progressBar。
        若你将来要显示每个 worker 的进度，可以维护 self.worker_progress 字典。
        """
        if not hasattr(self, 'worker_progress'):
            self.worker_progress = {}
        self.worker_progress[worker_id] = percent
        # 取所有已知 worker 的平均
        vals = list(self.worker_progress.values())
        avg = int(sum(vals) / max(1, len(vals)))
        try:
            self.progressBar.setValue(avg)
        except Exception:
            print("进度条更新失败：", avg)

    def handle_worker_finished(self, worker_id):
        """当某个 worker 发 finished 时的回调（把信息写到 textBrowser）"""
        now = datetime.now().strftime('%H:%M:%S.%f')[:-3]
        try:
            self.result_key.append(f"[{now}] worker {worker_id} finished.")
        except Exception:
            print("finished:", worker_id)
    def start_CBC(self):
        self.result_CBC.clear()
        text_CP = self.text_CBC.toPlainText().replace("\n","")
        key = self.key_CBC.text()
        initial_vector = self.initial_vector.text()
        result = ""
        if len(key) != 4:
            QMessageBox.information(self,"提示","秘钥需要4位，请重新输入",QMessageBox.Ok)
            return
        AES = S_AES(key)
        if self.CBC_Encryption.isChecked():
            result = AES.CBC_mode_Encryption(text_CP,key,initial_vector)
        elif self.CBC_Decryption.isChecked():
            if initial_vector == "":
                QMessageBox.information(self, "提示", "需要四位随机向量，请重新输入", QMessageBox.Ok)
                return
            result = AES.CBC_mode_Decryption(text_CP,key,initial_vector)

        self.showResult(text_CP,result,self.result_CBC,mode=True,iv=AES.initialVector)
        #self.showResult(text_CP,result,self.result_CBC)


if __name__=="__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())